Skip to content

feat: Add truncate function#855

Merged
owlstronaut merged 9 commits intonpm:mainfrom
pjohnmeyer:feat/add-truncate-function
May 7, 2026
Merged

feat: Add truncate function#855
owlstronaut merged 9 commits intonpm:mainfrom
pjohnmeyer:feat/add-truncate-function

Conversation

@pjohnmeyer
Copy link
Copy Markdown
Contributor

@pjohnmeyer pjohnmeyer commented May 3, 2026

This PR adds a truncate function to allow for portions of a version string "below" a certain level to be dropped.

The truncate function, as implemented in this first pass at a PR, returns a new valid version string. The function:

  1. Always removes build information
  2. Removes pre-release information, unless a pre-release type is passed as the truncation
  3. Zeroes out "lower" components of the semantic version (e.g. if the truncation performed is major, both minor and patch are zeroed)

An alternative I considered was returning strings without the valid version guarantee; for example, truncate('1.2.3', 'minor') === '1.2') instead of 1.2.0. This is not what was specified by @isaacs in #48, however, and seemed to be out of place for the rest of the library.

As a result, I also considered naming the function differently. One option I considered was floor, which seemed conceptually correct for major, minor, and patch. For truncation = 'pre*' however, this did not feel right, as truncate('1.2.3-rc1+build', 'prerelease') === '1.2.3-rc1', but since a) build metadata "...MUST be ignored when determining version precedence...", and b) there could be a 1.2.3-rc0 that is closer to the "floor", the name didn't seem right for that use case.

Lastly, I considered disallowing the pre* versions for the truncation argument, and only allowing major, minor, and patch. This, paired with the floor naming, was the most attractive alternative to me.

References

Related to #48

@pjohnmeyer pjohnmeyer requested a review from a team as a code owner May 3, 2026 00:37
@pjohnmeyer
Copy link
Copy Markdown
Contributor Author

pjohnmeyer commented May 3, 2026

FWIW: I don't have a stake in whether or not truncate is added to the library. I don't know if it's truly needed. I just saw an old issue and decided to work on it for fun. This also was useful for me to prepare to work on the dec function from #48, which I do actually see more of a use case for.

Also, I will note that template-oss-check failed and wanted me to update a bunch of .github files, but I did not include those per the CONTRIBUTING guidelines.

Copy link
Copy Markdown
Contributor

@mbtools mbtools left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could add some cases with prerelease and build to the fixtures, but LGTM 👍

Copy link
Copy Markdown
Contributor

@owlstronaut owlstronaut left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is great. I like the idea from @mbtools to add some prerelease+build fixtures. I'd like to see a test that verifies/catches the mutation i think happens.

orig = new SemVer('1.2.3-alpha+build')
snapshot = { orig stuff }
truncate(orig, 'major')
org === snapshot
 truncate(orig, 'patch') // second call should start from the orig

Comment thread README.md Outdated
Comment thread functions/truncate.js Outdated
return null
}

const parsed = parse(version, options)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think this returns the same instance of the SemVer class so you'll be mutating the caller's object.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point! I saw how inc does it and didn't understand why it didn't use parse -- now it makes sense.

Co-authored-by: Michael Smith <owlstronaut@github.com>
@pjohnmeyer
Copy link
Copy Markdown
Contributor Author

I like the idea from @mbtools to add some prerelease+build fixtures. I'd like to see a test that verifies/catches the mutation i think happens.

@owlstronaut yeah I agree. I covered that functionality with the valid-versions fixture, but that's a less obvious expression of intent.

@pjohnmeyer
Copy link
Copy Markdown
Contributor Author

@mbtools I added some fixtures to address your concern.

@owlstronaut I fixed the inadvertent mutation of input. Rather than add an explicit test for this, I used Object.freeze in the tests as an assurance.

Copy link
Copy Markdown
Contributor

@owlstronaut owlstronaut left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is excellent, thank you!

@owlstronaut owlstronaut merged commit 0d0a0a2 into npm:main May 7, 2026
25 of 29 checks passed
@pjohnmeyer pjohnmeyer deleted the feat/add-truncate-function branch May 8, 2026 17:28
@github-actions github-actions Bot mentioned this pull request Mar 20, 2026
owlstronaut pushed a commit that referenced this pull request May 8, 2026
🤖 I have created a release *beep* *boop*
---


## [7.8.0](v7.7.4...v7.8.0)
(2026-05-08)
### Features
*
[`0d0a0a2`](0d0a0a2)
[#855](#855) Add `truncate`
function (#855) (@pjohnmeyer, @owlstronaut)
### Bug Fixes
*
[`3905343`](3905343)
[#859](#859) Warn when defaulting
to --inc=patch in CLI (@pjohnmeyer)
### Documentation
*
[`c368af6`](c368af6)
[#853](#853) fix typos in
documentation (#853) (@ankitkumar572005)
*
[`37776c3`](37776c3)
[#846](#846) fix BNF grammar to
distinguish prerelease from build identifiers (#846) (@abhu85, @claude)
### Chores
*
[`9542e09`](9542e09)
[#860](#860) template-oss-apply
(@owlstronaut)
*
[`937bc2c`](937bc2c)
[#860](#860)
`template-oss-apply@5.0.0` (@owlstronaut)
*
[`6946fef`](6946fef)
[#852](#852) bump
@npmcli/template-oss from 4.29.0 to 4.30.0 (#852) (@dependabot[bot],
@npm-cli-bot)

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants